package com.wx.lambda.ii.chapter5;

import com.wx.lambda.ii.chapter2.Apple;
import com.wx.lambda.ii.chapter2.Chapter2Test;
import com.wx.lambda.ii.chapter4.Chapter4Test;
import com.wx.lambda.ii.chapter4.Dish;
import lombok.extern.slf4j.Slf4j;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 第5章测试
 */
@Slf4j
public class Chapter5Test {
    public static void main(String[] args) {

        /*
         * 将数组内每个单词拆分成字符，输出一个列表，列中是每个字符，要求相同字符只输出一次
         */
        List<String> strings = initData();
        // 方法一 ：
        Set<String> chars = new TreeSet<>();

        strings.stream()
                .map(s->s.split(""))
                .map(Arrays::stream)
                .forEach(s->s.forEach(chars::add));

        chars.forEach(log::info);
        log.info("================");
        // 方法二 ：
        strings.stream()
                .map(s -> s.split(""))
                .flatMap(Arrays::stream) // 多个流 合并成一个
                .distinct()
                .forEach(log::info);

        /*
         *  给定两个数字列表，如何返回所有的数对呢？例如，给定列表[1, 2, 3]和列表[3, 4]，应
         * 该返回[(1, 3), (1, 4), (2, 3), (2, 4), (3, 3), (3, 4)]。为简单起见，你可以用有两个元素的数组来代
         * 表数对。
         */
        List<Integer> list1 = Arrays.asList(1, 2, 3);
        List<Integer> list2 = Arrays.asList( 3, 4);

        list1.stream()
                .flatMap( i -> list2.stream().map(j -> new int[]{i, j}))
                .map(Arrays::toString)
                .forEach(log::info);

        log.info("================");
        // 如何扩展前一个例子，只返回总和能被3整除的数对呢？例如(2, 4)和(3, 3)是可以的

        list1.stream()
                .flatMap( i -> list2.stream().map(j -> new int[]{i, j}))
                .filter(a ->  (a[0] + a[1]) % 3 == 0)
                .map(Arrays::toString)
                .forEach(log::info);
        log.info("================");
        List<Integer> someNumbers = Arrays.asList(9,123, 1232, 3, 4, 5,6);
        someNumbers.stream().filter(n -> n % 3 == 0).map(i -> Integer.toString(i)).findAny().ifPresent(log::info);

        /*
         * 用 reduce 归约 来计算最大值和最小值
         */
        Integer maxInt = someNumbers.stream().reduce(0, (a, b) -> (a > b) ? a : b);
        Optional<Integer> reduce = someNumbers.stream().reduce((a, b) -> (a > b) ? b : a);

        log.info("maxInt = {}" , maxInt);
        reduce.ifPresent(a -> log.info("minInt = {}" , a));
        /*
         * 怎样用map和reduce方法数一数流中有多少个菜呢
         */
        List<Dish> dishes = Chapter4Test.initData();
        dishes.stream().map(dish -> 1).reduce(Integer::sum).map(String::valueOf).ifPresent(log::info);

    }

    static List<String> initData() {

        return Arrays.asList("Hello","world","this" ,"is","a","test");
    }


}
